<?php
/**
*
* ShopWindow Toolset
*
* Copyright (C) 2008 Digital Window Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
*/


require_once('class.api_client.php');
require_once('class.shopcore.php');


/**
 * Encapsulate the corresponding API functionality
 *
 */
class api_category_tree extends api_client
{
	var $iCategoryId = null;		// the category Id to which the categories belong

	/**
	 * Gets the category tree
	 *
	 * @copyright	DigitalWindow
 	 * @author		Kostas Melas <kostas@digitalwindow.com>
 	 *
	 * @param 	int 	 $oParams->iCategoryId
	 * @param 	bool	 $oParams->bExpandAllBranches
	 * 
	 * @return 	object	 Of type CategoryTree
	 */
	function getCategoryTree($oParams='')
	{
		// sanity check
		$this->iCategoryId	= $oParams->iCategoryId > 0 ? intval($oParams->iCategoryId) : $this->iCategoryId;
		$bExpandAllBranches	= $oParams->bExpandAllBranches === true ? true : false;
		
        $aParams = array('iCategoryId'=> $this->iCategoryId, 'bExpandAllBranches' => $bExpandAllBranches);

       	// make the SOAP call
        $this->call('getCategoryTree', $aParams);

        // Recurse, update, clean and return our tree
        $oTree = new stdClass();
        if (is_numeric(VERTICAL_CATEGORY_ID)) {
            // Build our mini tree based on a server response //
            $oVerticalTree = new stdClass();
            $oVerticalTree->oCategory = array($this->findVerticleParent($this->oResponse->oCategoryTree ));
            $oVerticalTree->iActiveNode = VERTICAL_CATEGORY_ID;
            
            $oTree = $this->updateTree( $oVerticalTree );
        }
        else {
            $oTree = $this->updateTree( $this->oResponse->oCategoryTree );
        }

		return $oTree;
	}
	
	/**
	 * Finds the branch of the tree that our verticle begins at
	 *
	 * @param Object of type category tree 
	 * @return Object of type category tree
	 */
	private function findVerticleParent( $oTree ) 
	{
	    if (empty($oTree)) {
	        return false;
	    }
	    
	    foreach ($oTree->oCategory as $oBranch) {
	        if ($oBranch->iId == VERTICAL_CATEGORY_ID) {
	            return $oBranch;
	        }
	        else {
	            if (!empty($oBranch->oCategoryTree)) {
    	            $oFoundBranch = $this->findVerticleParent($oBranch->oCategoryTree );
    	            if (!empty($oFoundBranch)) {
    	                return $oFoundBranch;
    	            }
	            }
	        }
	    }

	    return false;
	}
	
	/**
	 * Loop through the tree updating nodes if required. Will update any re-mapped
	 * category names and remove any non-vertical categorys.
	 *
	 * @param	Object	of type Category
	 * 
	 * @return	Object	of type Category
	 */
	private function updateTree( $oCategory )
	{
		$this->oShopCore = new shopcore();
		
		// is this from soap or local
		if (isset($oCategory->oCategory)) {
			$aChildren = $oCategory->oCategory;
			unset($oCategory->oCategory);
		}
		else {
			$aChildren = $oCategory->aChildren;
		}
		
		// If no children, return //
		if (empty($aChildren)) {
			return false;
		}
		
		// Use new array to stop empty children being added //
		$aRemainingChildren = array();
		
		foreach ( $aChildren as $oChild ) {

			if ( ($oChild->iParentId == null) && is_numeric(VERTICAL_CATEGORY_ID) && VERTICAL_CATEGORY_ID!=$oChild->iId ) {
				continue;
			}
			
			// Filter category
			$tmpChild = $this->filterCategories( array($oChild) );
			if ($tmpChild[0] == false) {
				continue;
			}
			
			// Filter returned array, first item is the child
			$oChild = $tmpChild[0];
			
			// If more children exist below current level. Call self and process them //
			if (is_object($oChild->oCategoryTree)) {
				$children = $oChild->oCategoryTree;
				$oChild->oCategoryTree = $this->updateTree( $children );
			}
			
			// Build sLink //
			$oChild->sLink = $this->oShopCore->buildLink(( $oChild->iParentId == 0 ? P_CATEGORY : P_PRODUCTLIST ), '', '', $oChild->iId);
			
			$aRemainingChildren[] = $oChild;
		}

		// sort children by name //
		usort($aRemainingChildren, array(&$this, "nameSort" ) );
	
		// set children to array 
		$oCategory->aChildren = $aRemainingChildren;
		
		return $oCategory;
	}
	
	/**
	 * Comparison function. Used in conjunction with uSort
	 *
	 * @param	Object	of type Child
	 * @param	Object	of type Child
	 * 
	 * @return	Int		-1 if A < B or 1 if B > C
	 */
	private function nameSort($oChildA, $oChildB )
	{
		if ( $oChildA->sName < $oChildB->sName) {
			return -1;
		}
		else {
			return 1;
		}
	}
} // class


?>